package com.anthill.controllers
{
import com.anthill.handlers.EventHandler;
import com.anthill.managers.Manager;
import com.anthill.utils.MetadataUtil;

import flash.events.Event;
import flash.events.IEventDispatcher;

import mx.events.FlexEvent;

/**
 *  Controller is main controller which should be placed in main App 
 *  and can contain Managers and EventHandlers.
 * 
 */ 
public class Controller extends EventBus
{
	include "../Version.as";
	
	/**
     *  Constructor. 
     *  
     */  
	public function Controller()
	{
		super();
	}

	[Bindable]
    /**
     *  Flag that indicates whether controller should parse metadata 
     *  of Managers to automatically create event listeners.
     *  
     *  @default true;
     */ 
	public var parseManagersMetadata:Boolean = true;
	
 	/**
     *  @private
     *  Storage for parseViewsMetadata property.
     */
	private var _parseViewsMetadata:Boolean = false;
	
	[Bindable]
	 /**
     *  Flag that indicates whether controller should parse metadata 
     *  of Views to automatically create event listeners.
     *
     *  @default false
     */ 	
	public function get parseViewsMetadata():Boolean
	{
		return _parseViewsMetadata;
	}

    /**
     *  @private
     */
	public function set parseViewsMetadata(v:Boolean):void
	{
		_parseViewsMetadata = v;
		// add internal listener to parse metadata of views if configured
		if(_parseViewsMetadata)
			addEventListener(FlexEvent.PREINITIALIZE, registrateEventHandler, true, int.MAX_VALUE, true);
		else if(hasEventListener(FlexEvent.PREINITIALIZE))
			removeEventListener(FlexEvent.PREINITIALIZE, registrateEventHandler);
	}

    /**
     *  @private
     */
	protected function registrateEventHandler(event:FlexEvent):void
	{
		// parse metadata of views
		eventHandlers = MetadataUtil.getEventHandlers(event.target as IEventDispatcher)
	}

 	/**
     *  @private
     *  Storage for managers property.
     */		
	private var _managers:Array = [];
	
	[Inspectable(category="General", arrayType="com.anthill.managers.Manager")]
	[Bindable("managersChanged")]
	/**
     *  Array that used to store Managers.
     *
     *  @default []
     */ 	
	public function get managers():Array
	{
		return _managers;
	}

	[ArrayElementType("com.anthill.managers.Manager")] 
  	/**
     *  @private
     *  Automatically adds event listeners if configured.
     */
	public function set managers(v:Array):void
	{
		_managers = v;
		
		// parse metadata of managers if configured
		if(parseManagersMetadata)
			for each(var manager:Manager in v)
			{
				eventHandlers = MetadataUtil.getEventHandlers(manager);
			}
		dispatchEvent(new Event("managersChanged"));
	}

	/**
     *  @private
     *  Storage for eventHandlers property.
     */	
	private var _eventHandlers:Array = [];
	
	[Inspectable(category="General", arrayType="com.anthill.handlers.EventHandler")]
	[Bindable("eventHandlersChanged")]
	/**
     *  Array that used to store eventHandlers.
     *
     *  @default []
     */ 
	public function get eventHandlers():Array
	{
		return _eventHandlers;
	}
	
	[ArrayElementType("com.anthill.handlers.EventHandler")] 
	/**
     *  @private
     *  Automatically adds event listeners.
     */
	public function set eventHandlers(v:Array):void
	{
		_eventHandlers = v;
		
		// add listeners for event handlers
		for each(var handler:EventHandler in v)
		{
			addEventListener(handler.type, handler.listener, handler.useCapture, handler.priority, handler.useWeakReference);
		}
		dispatchEvent(new Event("eventHandlersChanged"));
	}

}
}